package com.hongshu.web.service.recommendation;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hongshu.common.core.domain.NoteSearchVo;
import com.hongshu.common.core.utils.bean.BeanUtils;
import com.hongshu.web.auth.AuthContextHolder;
import com.hongshu.web.domain.dto.SystemConfigDTO;
import com.hongshu.web.domain.entity.WebNote;
import com.hongshu.web.mapper.web.WebNoteMapper;
import com.hongshu.web.service.RecommendNoteServiceImpl;
import com.hongshu.web.service.recommendation.model.RankingItem;
import com.hongshu.web.service.recommendation.model.RecommendContext;
import com.hongshu.web.service.recommendation.model.UserProfile;
import com.hongshu.web.service.sys.ISysSystemConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 现代化混合推荐服务
 * 保留原有ES和MySQL实现，新增混合推荐算法
 *
 * @author hongshu
 * @date 2024/01/01
 */
@Service
@Slf4j
public class ModernRecommendationService {

    @Autowired
    private RecallService recallService;
    @Autowired
    private RankingService rankingService;
    @Autowired
    private RerankService rerankService;
    @Autowired
    private UserProfileService userProfileService;
    @Autowired
    private RecommendNoteServiceImpl originalRecommendService; // 保留原有服务
    @Autowired
    private ISysSystemConfigService systemConfigService;
    @Autowired
    private WebNoteMapper noteMapper;


    /**
     * 混合推荐主入口
     * 支持多种推荐策略切换
     */
    public Page<NoteSearchVo> getRecommendNotes(long currentPage, long pageSize) {
        try {
            SystemConfigDTO systemConfig = systemConfigService.getSystemConfig();
            String strategy = systemConfig.getQueryPrimary();
            // 根据策略选择推荐方式
            switch (strategy.toLowerCase()) {
                case "hybrid":
                    return getHybridRecommendations(currentPage, pageSize);
                case "es":
                    return getESRecommendations(currentPage, pageSize);
                case "mysql":
                    return getMySQLRecommendations(currentPage, pageSize);
                case "auto":
                    return getAutoRecommendations(currentPage, pageSize);
                default:
                    log.warn("未知推荐策略: {}, 使用混合推荐", strategy);
                    return getHybridRecommendations(currentPage, pageSize);
            }
        } catch (Exception e) {
            log.error("推荐服务异常，降级到mysql推荐", e);
            return getMySQLRecommendations(currentPage, pageSize);
        }
    }

    /**
     * 混合推荐算法实现
     */
    private Page<NoteSearchVo> getHybridRecommendations(long currentPage, long pageSize) {
        try {
            // 1. 获取用户画像
            UserProfile userProfile = userProfileService.getCurrentUserProfile();
            // 2. 构建推荐上下文
            RecommendContext context = RecommendContext.builder()
                    .currentPage(currentPage)
                    .pageSize(pageSize)
                    .timestamp(System.currentTimeMillis())
                    .build();
            // 3. 多路召回
            List<String> candidateItems = recallService.multiRecall(userProfile, context);
            log.info("多路召回获得候选物品数量: {}", candidateItems.size());
            // 3.1 召回为空兜底
            if (candidateItems == null || candidateItems.isEmpty()) {
                log.warn("召回为空，使用MySQL热榜兜底");
                return getHotFromMysql(currentPage, pageSize);
            }
            // 4. 机器学习排序
            List<RankingItem> rankedItems = rankingService.rankItems(candidateItems, userProfile, context);
            log.info("排序后物品数量: {}", rankedItems.size());
            // 5. 重排序
            List<String> finalItems = rerankService.rerank(rankedItems, userProfile, context);
            log.info("重排序后物品数量: {}", finalItems.size());
            // 5.1 重排为空兜底
            if (finalItems == null || finalItems.isEmpty()) {
                log.warn("重排为空，使用MySQL热榜兜底");
                return getHotFromMysql(currentPage, pageSize);
            }
            // 6. 转换为VO对象
            return convertToNoteVo(finalItems, userProfile);
        } catch (Exception e) {
            log.error("混合推荐异常", e);
            // 全局兜底：MySQL热榜
            return getHotFromMysql(currentPage, pageSize);
        }
    }

    /**
     * ES推荐实现
     * 使用原有的ES推荐算法
     */
    private Page<NoteSearchVo> getESRecommendations(long currentPage, long pageSize) {
        try {
            // 获取当前用户ID
            String userId = AuthContextHolder.getUserId();
            if (userId == null) {
                log.warn("用户未登录，无法使用ES推荐");
                return getHybridRecommendations(currentPage, pageSize);
            }
            // 调用原有的ES推荐方法
            List<NoteSearchVo> esResults = originalRecommendService.getRecommendNote(Long.parseLong(userId));
            Page<NoteSearchVo> page = new Page<>();
            page.setTotal(esResults.size());
            page.setRecords(esResults);
            return page;
        } catch (Exception e) {
            log.error("ES推荐异常", e);
            return getHybridRecommendations(currentPage, pageSize);
        }
    }

    /**
     * MySQL推荐实现
     * 使用原有的MySQL推荐算法
     */
    private Page<NoteSearchVo> getMySQLRecommendations(long currentPage, long pageSize) {
        try {
            // 获取当前用户ID
            String userId = AuthContextHolder.getUserId();
            if (userId == null) {
                log.warn("用户未登录，无法使用MySQL推荐");
                // 未登录：直接热榜兜底
                return getHotFromMysql(currentPage, pageSize);
            }
            // 调用原有的MySQL推荐方法
            Page<NoteSearchVo> mysqlResults = originalRecommendService.getRecommendNoteFromMysql(userId, currentPage, pageSize);
            // 转换为NoteVo
            return convertNoteSearchVoToNoteVo(mysqlResults.getRecords());
        } catch (Exception e) {
            log.error("MySQL推荐异常", e);
            return getHotFromMysql(currentPage, pageSize);
        }
    }

    /**
     * 自动推荐策略
     * 根据用户特征自动选择最佳推荐方式
     */
    private Page<NoteSearchVo> getAutoRecommendations(long currentPage, long pageSize) {
        try {
            UserProfile userProfile = userProfileService.getCurrentUserProfile();
            // 根据用户特征选择推荐策略
            if (userProfile.isNewUser()) {
                // 新用户使用混合推荐
                return getHybridRecommendations(currentPage, pageSize);
            } else if (userProfile.getBehaviorCount() < 10) {
                // 行为较少的用户使用ES推荐
                return getESRecommendations(currentPage, pageSize);
            } else {
                // 活跃用户使用混合推荐
                return getHybridRecommendations(currentPage, pageSize);
            }
        } catch (Exception e) {
            log.error("自动推荐异常", e);
            return getESRecommendations(currentPage, pageSize);
        }
    }

    /**
     * 转换NoteSearchVo到RecommendNoteVo
     */
    private Page<NoteSearchVo> convertNoteSearchVoToNoteVo(List<NoteSearchVo> noteSearchVos) {
        Page<NoteSearchVo> page = new Page<>(1, noteSearchVos == null ? 0 : noteSearchVos.size());
        if (noteSearchVos == null || noteSearchVos.isEmpty()) {
            page.setTotal(0);
            page.setRecords(java.util.Collections.emptyList());
            return page;
        }
        page.setTotal(noteSearchVos.size());
        page.setRecords(noteSearchVos);
        return page;
    }

    /**
     * 转换为推荐笔记VO
     */
    private Page<NoteSearchVo> convertToNoteVo(List<String> itemIds, UserProfile userProfile) {
        Page<NoteSearchVo> page = new Page<>(1, itemIds == null ? 0 : itemIds.size());
        if (itemIds == null || itemIds.isEmpty()) {
            page.setTotal(0);
            page.setRecords(java.util.Collections.emptyList());
            return page;
        }
        // 批量查询笔记并转换
        java.util.List<WebNote> notes = noteMapper.selectBatchIds(itemIds);
        java.util.List<NoteSearchVo> records = new java.util.ArrayList<>();
        for (WebNote note : notes) {
            NoteSearchVo vo = new NoteSearchVo();
            BeanUtils.copyProperties(note, vo);
            records.add(vo);
        }
        page.setTotal(records.size());
        page.setRecords(records);
        return page;
    }

    /**
     * 兜底：从MySQL获取热榜（审核通过），按点赞/收藏/更新时间降序
     */
    private Page<NoteSearchVo> getHotFromMysql(long currentPage, long pageSize) {
        Page<WebNote> notePage = noteMapper.selectPage(
                new Page<>(currentPage, pageSize),
                new QueryWrapper<WebNote>()
                        .eq("audit_status", com.hongshu.common.core.enums.AuditStatusEnum.PASS.getCode())
                        .orderByDesc("like_count")
                        .orderByDesc("collection_count")
                        .orderByDesc("update_time")
        );
        Page<NoteSearchVo> page = new Page<>(notePage.getCurrent(), notePage.getSize());
        page.setTotal(notePage.getTotal());
        java.util.List<NoteSearchVo> list = new java.util.ArrayList<>();
        for (WebNote note : notePage.getRecords()) {
            NoteSearchVo vo = new NoteSearchVo();
            BeanUtils.copyProperties(note, vo);
            list.add(vo);
        }
        page.setRecords(list);
        return page;
    }
}


